package org.cmd;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;

/**
 * Useful methods for command applications.
 *
 * @author See <a href="the Google Code page of the easy-utils
 * library">http://code.google.com/p/easy-utils/</a> for collaborators and other
 * information.
 */
public abstract class CommandShell {

    /**
     * Displays a menu, returning a guaranteed right choice. First choice index
     * corresponds to 1.
     *
     * @param choices {@link ArrayList} of {@link String} The choices to be
     * displayed.
     * @param errMsg {@link String} The message to display if an input is
     * invalid.
     * @param chooseMsg {@link String} The message to use when asking the user
     * for input.
     * @return An integer representing the number of the chosen choice, or -1 if
     * there were no choices.
     */
    public static int createMenu(ArrayList<String> choices, String errMsg, String chooseMsg) {
        boolean errExist;
        int numChoice = -1;
        String choice;
        Scanner key = new Scanner(System.in);

        if (choices == null || choices.isEmpty()) {
            return -1;
        }

        do {
            errExist = false;
            System.out.println(chooseMsg);
            for (Iterator<String> it = choices.iterator(); it.hasNext();) {
                String target = it.next();
                int questionIndex = choices.indexOf(target) + 1;
                System.out.println(questionIndex + " - " + target);
            }
            choice = key.nextLine();
            try {
                if ((numChoice = Integer.parseInt(choice)) > choices.size() || numChoice < 1) {
                    errExist = true;
                }
            } catch (NumberFormatException ex) {
                errExist = true;
            }
            if (errExist) {
                System.out.println(errMsg);
            }
        } while (errExist);
        return numChoice;
    }

    /**
     * Gets an user input as a String.
     *
     * @return {@link String} The input.
     */
    public static String getInputAsString() {
        return new Scanner(System.in).nextLine();
    }

    /**
     * Gets an user input as an int. Inputs not turnable into int aren't
     * accepted, and therefore the user is asked once again for a new input.
     *
     * @param errMsg {@link String} The message to display if the input can't be
     * turned into an int.
     * @return An integer representing the input.
     */
    public static int getInputAsInt(String errMsg) {
        try {
            return Integer.parseInt(new Scanner(System.in).nextLine());
        } catch (NumberFormatException ex) {
            System.out.println(errMsg);
            return CommandShell.getInputAsInt(errMsg);
        }
    }

    /**
     * Gets an user input as a float. Inputs not turnable into float aren't
     * accepted, and therefore the user is asked once again for a new input.
     *
     * @param errMsg {@link String} The message to display if the input can't be
     * turned into a float.
     * @return A float representing the input.
     */
    public static float getInputAsFloat(String errMsg) {
        try {
            return Float.parseFloat(new Scanner(System.in).nextLine());
        } catch (NumberFormatException ex) {
            System.out.println(errMsg);
            return CommandShell.getInputAsFloat(errMsg);
        }
    }

    /**
     * Gets an user input as a double. Inputs not turnable into double aren't
     * accepted, and therefore the user is asked once again for a new input.
     *
     * @param errMsg {@link String} The message to display if the input can't be
     * turned into a double.
     * @return A double representing the input.
     */
    public static double getInputAsDouble(String errMsg) {
        try {
            return Double.parseDouble(new Scanner(System.in).nextLine());
        } catch (NumberFormatException ex) {
            System.out.println(errMsg);
            return CommandShell.getInputAsDouble(errMsg);
        }
    }

    /**
     * Gets an user input as a boolean.
     *
     * @return A boolean representing the input.
     */
    public static boolean getInputAsBoolean() {
        return Boolean.parseBoolean(new Scanner(System.in).nextLine());
    }

    /**
     * Gets an user input as a byte. Inputs not turnable into byte aren't
     * accepted, and therefore the user is asked once again for a new input.
     *
     * @param errMsg The message to display if the input can't be turned into a
     * byte.
     * @return A byte representing the input.
     */
    public static byte getInputAsByte(String errMsg) {
        try {
            return Byte.parseByte(new Scanner(System.in).nextLine());
        } catch (NumberFormatException ex) {
            System.out.println(errMsg);
            return CommandShell.getInputAsByte(errMsg);
        }
    }
}
